#include "enpclientfactory.h"

CEnpClientFactory::CEnpClientFactory()
{
}

CEnpClientFactory::~CEnpClientFactory()
{
    // 释放所有的
}

int CEnpClientFactory::Init(const char* pszBuffer, size_t iBufferSize, int iObjectCount)
{
    CT_ASSERT(CountSize(iObjectCount) == iBufferSize);

    int iRet = 0;
    iRet = m_stMgr.Init(pszBuffer, iObjectCount, sizeof(CEnpClient),
        LIST_COUNT, INDEX_COUNT);
    CHECK_RETURN(iRet);

    return 0;
}

size_t CEnpClientFactory::CountSize(int iObjectCount)
{
    return CTObjectMgr<CEnpClient>::CountSize(iObjectCount,
        sizeof(CEnpClient), LIST_COUNT, INDEX_COUNT);
}

CEnpClient* CEnpClientFactory::Alloc()
{
    int i = m_stMgr.InfoListAlloc(ALLOC_INDEX, USED_LIST);
    if (i < 0)
    {
        CT_WARNING(("alloc client failed %d", i));
        return NULL;
    }

    CEnpClient* pstClient = new (&m_stMgr[i]) CEnpClient;
    pstClient->m_stNetHead.uiHandle = i;
    return pstClient;
}

int CEnpClientFactory::Free(CEnpClient* pstClient)
{
    int i = CalcObjectPos(pstClient);

    m_stMgr.InfoListMove(i, REMAIN_INDEX, EMPTY_LIST);    
    m_stMgr.InfoListMove(i, ALLOC_INDEX, FREE_LIST);

    // 析构
    pstClient->~CEnpClient();
    return 0;
}

CEnpClient* CEnpClientFactory::CalcObject(int iIndex)
{
    if (iIndex < 0 || iIndex >= m_stMgr.GetObjectCount())
    {
        return NULL;
    }

    return &m_stMgr[iIndex];
}

int CEnpClientFactory::CalcObjectPos(const CEnpClient* pstClient) const
{
    int i = (char*)pstClient - (char*)&m_stMgr[0];
    CT_ASSERT(i % sizeof(CEnpClient) == 0);
    return i / sizeof(CEnpClient);
}

int CEnpClientFactory::SetEmpty(CEnpClient* pstClient)
{
    int i = CalcObjectPos(pstClient);

    switch (m_stMgr.Flag(i, REMAIN_INDEX))
    {
    case EMPTY_LIST:
        return 0;

    case REMAIN_LIST:
        return m_stMgr.InfoListMove(i, REMAIN_INDEX, EMPTY_LIST);

    default:
        CT_WARNING(("client(%d) invalid listid %d", i, m_stMgr.Flag(i, REMAIN_INDEX)));
        return -1;
    }
}

int CEnpClientFactory::SetRemain(CEnpClient* pstClient)
{
    int i = CalcObjectPos(pstClient);

    switch (m_stMgr.Flag(i, REMAIN_INDEX))
    {
    case EMPTY_LIST:
        return m_stMgr.InfoListMove(i, REMAIN_INDEX, REMAIN_LIST);

    case REMAIN_LIST:
        return 0;

    default:
        CT_WARNING(("client(%d) invalid listid %d", i, m_stMgr.Flag(i, REMAIN_INDEX)));
        return -1;
    }
}

bool CEnpClientFactory::IsEmpty(CEnpClient* pstClient)
{
    int i = CalcObjectPos(pstClient);
    return m_stMgr.Flag(i, REMAIN_INDEX) == EMPTY_LIST;
}
